package st.learnopengl.apps.basic

import glm_.glm
import glm_.mat4x4.Mat4
import glm_.vec3.Vec3
import glm_.vec4.Vec4
import gln.*
import gln.draw.DrawMode
import gln.draw.glDrawArrays
import gln.glf.VertexAttribute
import gln.identifiers.GlBuffer
import gln.identifiers.GlProgram
import gln.identifiers.GlTexture
import gln.vertexArray.GlVertexArray
import gln.vertexArray.glGenVertexArray
import st.learnopengl.common.App
import st.learnopengl.common.GLUT
import org.lwjgl.opengl.GL11C.GL_COLOR_BUFFER_BIT
import org.lwjgl.opengl.GL11C.glClear
import org.lwjgl.opengl.GL13C.GL_TEXTURE0
import org.lwjgl.opengl.GL13C.glActiveTexture

class CoordinateSystem(width: Int, height: Int, title: String) : App(width, height, title) {

    private var program: GlProgram? = null
    private var sample1Location : Int = -1
    private var transformLocation: Int = -1
    private var vao: GlVertexArray? = null
    private var vbo: GlBuffer? = null
    private var texture: GlTexture? = null
    private lateinit var vertexAttr: VertexAttribute
    private lateinit var uvAttr: VertexAttribute

    override fun onInit() {
        program = GLUT.createProgram("shaders/coordinate/vertexShader.glsl"
            , "shaders/coordinate/fragmentShader.glsl")

        sample1Location = program!!.getUniformLocation("ourTexture1")
        transformLocation = program!!.getUniformLocation("transform")

        vao = GlVertexArray(glGenVertexArray()).bound {
            vbo = GlBuffer.gen()
            vbo!!.bound(BufferTarget.ARRAY) {
                var vertexs = floatArrayOf(
                    // positions          // texture coords
                    0.5f,  0.5f, 0.0f,   1.0f, 1.0f, // top right
                    0.5f, -0.5f, 0.0f,   1.0f, 0.0f, // bottom right
                    -0.5f, -0.5f, 0.0f,   0.0f, 0.0f, // bottom left
                    -0.5f,  0.5f, 0.0f,   0.0f, 1.0f  // top left
                )

                data(vertexs, Usage.STATIC_DRAW)
            }
        }

        vertexAttr = VertexAttribute(0, 3, VertexAttrType.FLOAT, false, 5 * 4, 0)
        uvAttr = VertexAttribute(1, 2, VertexAttrType.FLOAT, false, 5 * 4, 3 * 4)

        texture = GLUT.loadTexture("textures/brickwall.jpg")

        glClearColor(Vec4(0.3, 0.4, 0.5, 1.0))
    }

    override fun loop() {
        glClear(GL_COLOR_BUFFER_BIT)

        var m = Mat4(1.0f)
        m = m.rotate(glm.radians(55.0f), Vec3(1.0, 0.0, 0.0))
        var view = glm.lookAt(Vec3(0, 0, 3), Vec3(0, 0, 0), Vec3(0, 1, 0))
        var projection = glm.perspective(glm.radians(60.0f), 4.0f / 3.0f, 0.01f, 1000.0f)

        var transform = projection * view * m

        program!!.use {
            program.programUniform(transformLocation, transform)
            program.programUniform(sample1Location, 0)

            texture!!.bind(TextureTarget._2D)
            glActiveTexture(GL_TEXTURE0)

            vao!!.bind()
            vbo!!.bind(BufferTarget.ARRAY)

            vertexAttr.enable()
            vertexAttr.pointer()

            uvAttr.enable()
            uvAttr.pointer()

            glDrawArrays(DrawMode.TRIANGLE_FAN, 4)
        }
    }

    companion object {
        @JvmStatic
        fun main(args: Array<String>) {
            st.learnopengl.apps.basic.CoordinateSystem(1280, 720, "Coordinate System").run()
        }
    }
}